package com.bizmda.bizsip.app.checkrule;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONObject;
import com.bizmda.bizsip.app.controlrule.ControlRule;
import com.bizmda.bizsip.common.BizException;
import com.bizmda.bizsip.common.BizResultEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author shizhengye
 */
@Slf4j
public class ControlRuleHelper {
    private static final ExecutorService serviceCheckExecutorService = ThreadUtil.newExecutor(Runtime.getRuntime().availableProcessors());

    private ControlRuleHelper() {

    }

    public static List<ControlRuleResult> controlRule(JSONObject jsonObject, List<ControlRule> controlRuleList) throws BizException {
        CompletionService<ControlRuleResult> service = new ExecutorCompletionService<>(serviceCheckExecutorService);
        List<Future<ControlRuleResult>> futureList = new ArrayList<>();
        List<ControlRuleResult> controlRuleResultList = new ArrayList<>();
        int i = 0;
        for (ControlRule controlRule : controlRuleList) {
            Future<ControlRuleResult> future = service.submit(new ControlRuleThread(i,jsonObject, controlRule));
            futureList.add(future);
            controlRuleResultList.add(null);
            i++;
        }
        for (ControlRule controlRule : controlRuleList) {
            ControlRuleResult controlRuleResult = takeControlRuleResult(service);
            controlRuleResultList.set(controlRuleResult.getIndex(),controlRuleResult);
        }
        return controlRuleResultList;
    }

    private static ControlRuleResult takeControlRuleResult(CompletionService<ControlRuleResult> service) throws BizException {
        Future<ControlRuleResult> take;
        try {
            take = service.take();
        } catch (InterruptedException e) {
            log.error("控制规则计算take()被中断:",e);
            Thread.currentThread().interrupt();
            throw new BizException(BizResultEnum.CONTROLRULE_SERVICE_CHECK_THREAD_ERROR, e);
        }
        ControlRuleResult controlRuleResult;
        try {
            controlRuleResult = take.get();
        } catch (InterruptedException e) {
            log.error("控制规则计算get()被中断:",e);
            Thread.currentThread().interrupt();
            throw new BizException(BizResultEnum.CONTROLRULE_SERVICE_CHECK_THREAD_ERROR, e);
        } catch (ExecutionException e) {
            log.error("控制规则计算被中断:",e);
            Throwable throwable = e.getCause();
            if (throwable instanceof BizException) {
                throw (BizException) throwable;
            }
            throw new BizException(BizResultEnum.CONTROLRULE_SERVICE_CHECK_THREAD_ERROR, e);
        }
        log.debug("rule[{}]返回结果:{}",controlRuleResult.getName(),controlRuleResult.getResult());
        return controlRuleResult;
    }
}
